#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/unistd.h>

#include "entry-header.S"

ENTRY(led_on)
	/* 5、打开LED0
	 * 设置GPIO1_IO03输出低电平
	 */
	ldr r0, =0X0209C000	/*寄存器GPIO1_DR */
	ldr r1, =0		
	str r1,[r0]
	mov pc, lr
ENDPROC(led_on)

	.align	5
/*
 * This is the fast syscall return path.  We do as little as
 * possible here, and this includes saving r0 back into the SVC
 * stack.
 */
ret_fast_syscall:
	disable_irq				@ disable interrupts
	ldr	r1, [tsk, #TI_FLAGS]
	@ tst	r1, #_TIF_WORK_MASK
	@ bne	fast_work_pending
	b	fast_work_pending

	/* perform architecture specific actions before user return */
	@ arch_ret_to_user r1, lr

	restore_user_regs fast = 1, offset = S_OFF

/*
 * Ok, we need to do extra processing, enter the slow path.
 */
fast_work_pending:
	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
work_pending:
	tst	r1, #_TIF_NEED_RESCHED
	bne	work_resched
	@ b	work_resched
	@ tst	r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
	@ beq	no_work_pending
	b	no_work_pending
	@ mov	r0, sp				@ 'regs'
	@ mov	r2, why				@ 'syscall'
	@ bl	do_notify_resume
	@ b	ret_slow_syscall		@ Check work again

work_resched:
	bl	schedule
/*
 * "slow" syscall return path.  "why" tells us if this was a real syscall.
 */
ENTRY(ret_to_user)
ret_slow_syscall:
	disable_irq				@ disable interrupts
	@ ldr	r1, [tsk, #TI_FLAGS]
	@ tst	r1, #_TIF_WORK_MASK
	@ bne	work_pending
	@ b	work_pending
no_work_pending:
	/* perform architecture specific actions before user return */
	@ arch_ret_to_user r1, lr

	restore_user_regs fast = 0, offset = 0
ENDPROC(ret_to_user)

/*
 * This is how we return from a fork.
 */
ENTRY(ret_from_fork)
	@ bl	schedule_tail
	@ get_thread_info tsk
	@ ldr	r1, [tsk, #TI_FLAGS]		@ check for syscall tracing
	@ mov	why, #1
	@ tst	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
	@ beq	ret_slow_syscall
	@ mov	r1, sp
	@ mov	r0, #1				@ trace exit [IP = 1]
	@ bl	syscall_trace
	b	ret_slow_syscall
ENDPROC(ret_from_fork)

	.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S"
#undef CALL
#define CALL(x) .long x

/*=============================================================================
 * SWI handler
 *-----------------------------------------------------------------------------
 */
	.align	5
ENTRY(vector_swi)
	sub	sp, sp, #S_FRAME_SIZE
	stmia	sp, {r0 - r12}			@ Calling r0 - r12
	add	r8, sp, #S_PC
	stmdb	r8, {sp, lr}^			@ Calling sp, lr
	mrs	r8, spsr			@ called from non-FIQ mode, so ok.

	str	lr, [sp, #S_PC]			@ Save calling PC
	str	r8, [sp, #S_PSR]		@ Save CPSR
	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
	zero_fp

	/*
	 * Get the system call number.
	 */
	enable_irq

	get_thread_info tsk
	adr	tbl, sys_call_table		@ load syscall table pointer
	@ ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing

	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
	@ tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
	@ bne	__sys_trace

	cmp	scno, #NR_syscalls		@ check upper syscall limit
	adr	lr, ret_fast_syscall	@ return address
	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine

	add	r1, sp, #S_OFF
2:	mov	why, #0				@ no longer a real syscall
	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
	@ bcs	arm_syscall	
	b	sys_ni_syscall			@ not private func
ENDPROC(vector_swi)

	.type	sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"

/*============================================================================
 * Special system call wrappers
 */
@ r0 = syscall number
@ r8 = syscall table
sys_fork_wrapper:
		add	r0, sp, #S_OFF
		b	sys_fork
ENDPROC(sys_fork_wrapper)

sys_execve_wrapper:
		add	r3, sp, #S_OFF
		b	sys_execve
ENDPROC(sys_execve_wrapper)

/*
 * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
 * offset, we return EINVAL.
 */
sys_mmap2:
@ #if PAGE_SHIFT > 12
@ 		tst	r5, #PGOFF_MASK
@ 		moveq	r5, r5, lsr #PAGE_SHIFT - 12
@ 		streq	r5, [sp, #4]
@ 		beq	do_mmap2
@ 		mov	r0, #-EINVAL
@ 		mov	pc, lr
@ #else
		str	r5, [sp, #4]
		b	do_mmap2
@ #endif
ENDPROC(sys_mmap2)
